package edu.ustb.eureka.contract;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;

import com.netflix.appinfo.InstanceInfo;
import com.sleepycat.persist.model.Entity;
import edu.ustb.sc.definitions.ContractActionInfo;
import edu.ustb.sc.definitions.ContractTemplate;
import edu.ustb.sc.definitions.SpescConditionCheckStatus;
import edu.ustb.sc.definitions.SpescContractTerm;

import org.springframework.cloud.netflix.eureka.server.InstanceRegistry;

@Entity
public class RegistrationContract extends ContractTemplate {

	// weather-forecast服务提供方与注册中心订立的合约
	public RegistrationContract() {
		parties = new LinkedList<>();
		parties.add(new RegistrationContractParty("Platform"));
		parties.add(new RegistrationContractParty("WEATHER-FORECAST"));

		canTermNames = new ArrayList<>();
		mustTermNames = new ArrayList<>();
		cannotTermNames = new ArrayList<>();
		termName2Action = new HashMap<>();
		canTermNames.add("term_1");
		termName2Action.put("term_1", "commit");
		mustTermNames.add("term_2");
		termName2Action.put("term_2", "register");

		didMap = new HashMap<>();
	}

	@Override
	protected SpescContractTerm termNameMatchObj(String termName) {
		if (termName.equals("term_1")) {
			return new RegistrationContractTerm1();
		} else if (termName.equals("term_2")) {
			return new RegistrationContractTerm2();
		}
		return null;
	}

	@Override
	public String getAvailableActions(String party) {
		StringBuilder strBuilder = new StringBuilder();
		strBuilder.append(party + ": \n");
		try {
			ContractActionInfo actionInfo = new ContractActionInfo(
					RegistrationContract.class.getMethod("commit", String.class),
					new Object[0]
			);
			RegistrationContractTerm1 term_1 = new RegistrationContractTerm1(actionInfo);
			if (term_1.whenPreCondition(this) == SpescConditionCheckStatus.Yes) {
				strBuilder.append(party + " can " + term_1.getActionName() + " \n");
			}
			actionInfo = new ContractActionInfo(
					InstanceRegistry.class.getMethod("register", InstanceInfo.class, boolean.class),
					new Object[]{"service"}
			);
			RegistrationContractTerm2 term_2 = new RegistrationContractTerm2(actionInfo);
			if (term_2.whenPreCondition(this, actionInfo) == SpescConditionCheckStatus.Yes) {
				strBuilder.append(party + " must " + term_2.getActionName() + " \n");
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return strBuilder.toString();
	}

	@Override
	public ContractActionInfo getUrgentMustTermAction() {
		return null;
	}

	// commit动作在客户端实现，这里在服务端定义的动作相当于一个动作执行标志（Pointcut）
	public boolean commit(String serviceName) {
		return true;
	}
}
